import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'dva';
import { Icon } from 'react-fa';
import {
  Form,
  AutoComplete,
  Upload,
  DatePicker,
  Switch,
  Input,
  InputNumber,
  Button,
  Tree
} from 'antd';
import Select from '@/components/Select'
import Grid from '@/components/Grid';
import Layout from '@/components/Layout';
import Dialog from '@/components/Dialog';
import settings/*, { getPagination }*/ from '@/settings';
import { getData, formatUrl, getQueryKeywords, createAction } from '@/utils';
import { getNodes, search } from '@/services/dictionary';
import api from '@/api';

const ModelForm = Form.create()(props => {
  const dispatch = useDispatch()

  const { 
    node = {}
  } = useSelector(_ => _.dictionary)

  const {
    id,
    form: { validateFieldsAndScroll, getFieldDecorator }
  } = props

  useEffect(() => {
    if (id) {
      dispatch(createAction('dictionary/fetchNode')({
        id,
      }));
    }
  }, [dispatch, id]);

  const handleSubmit = (_, callback) => {
    validateFieldsAndScroll((err, values) => {
      if (!err) {
        callback(values);
      }
    });
  };

  props.register(handleSubmit)

  return (
    <Form layout="vertical">
      <Form.Item label="节点名称">
        {getFieldDecorator('name', {
          rules: [
            {
              required: true,
              message: '请输入节点名称',
            },
          ],
          initialValue: node.name,
        })(<Input placeholder="请输入节点名称" disabled={ id != null } />)}
      </Form.Item>
      <Form.Item label="节点值">
        {getFieldDecorator('value', {
          rules: [
            {
              required: true,
              message: '请输入节点值',
            },
          ],
          initialValue: node.value,
        })(<Input placeholder="请输入" />)}
      </Form.Item>
      <Form.Item label="节点描述">
        {getFieldDecorator('desc', {
          // rules: [
          //   {
          //     message: '请输入至少五个字符的描述！',
          //     min: 5,
          //   },
          // ],
          initialValue: node.desc,
        })(<Input.TextArea rows={8} placeholder="请输入备注信息" />)}
      </Form.Item>
    </Form>
  );
})

// const types = [{
//     id: 0,
//     name: 'String',
//     desc: '字符串形式'
//   }, {
//     id: 1,
//     name: 'Bytes',
//     desc: 'base64(utf-8)的形式'
//   }, {
//     id: 2,
//     name: 'Long',
//     desc: '字符串形式'
//   }, {
//     id: 3,
//     name: 'Double',
//     desc: '字符串形式'
//   }, {
//     id: 4,
//     name: 'Date',
//     desc: 'yyyy-MM-dd HH:mm:ss的格式'
//   }, {
//     id: 5,
//     name: 'Boolean',
//     desc: '“0”为false，非“0”为true'
//   }, {
//     id: 6,
//     name: 'BigDecimal',
//     desc: '字符串形式'
//   }]

const types = [{
    id: 1,
    name: '字符串'
  }, {
    id: 2,
    name: '数值型'
  }, {
    id: 3,
    name: '日期类型'
  }, {
    id: 4,
    name: '布尔值'
  }, {
    id: 5,
    name: '附件'
  }]

const ModelAttrForm = Form.create()(props => {
  const dispatch = useDispatch()
  const [fileList, setFileList] = useState([])

  const { 
    data = {}
  } = useSelector(_ => _.dictionary)

  const {
    id,
    form: { validateFields, validateFieldsAndScroll, getFieldDecorator, getFieldValue, setFieldsValue, resetFields }
  } = props

  const nodeid = props.data ? props.data.nodeid : null

  useEffect(() => {
    if (nodeid && id) {
      dispatch(createAction('dictionary/fetchOne')({
        nodeid,
        id, // 即：name，前端过滤
      }));
    }
  }, [dispatch, nodeid, id]);

  const type = getFieldValue('ctype') || data.ctype

  const handleSubmit = (_, callback) => {
    validateFieldsAndScroll((err, values) => {
      if (!err) {
        callback(values);
      }
    });
  };
  props.register(handleSubmit)

  // const options = types.map(_ => <Select.Option key={_.id} value={_.id}><span className="text-info">{_.name}</span>{`（${_.desc}）`}</Select.Option>)
  const options = types.map(_ => <Select.Option key={_.id} value={_.id}><span className="text-info">{_.name}</span></Select.Option>)

  const onTypeChange = value => {
    resetFields(['value'])
    // setFieldsValue({
    //   ctype: value
    // })
  }

  let WrapComponent = null
          
  switch(type) {
    // case 1 :
    case 5 :
      // const upload = {
      //   name: 'file',
      //   className: 'x-upload',
      //   // beforeUpload: handleUploadStart,
      //   showUploadList: false,
      //   // fileList: files,
      //   // onChange: handleUploadChange,
      //   multiple: true,
      //   action: `${settings.base}/file/upload`,
      //   data: {
      //     nodeid
      //   }
      // }
      // WrapComponent = <Upload {...upload}><Button icon="upload">上传文件</Button></Upload>
      const params = {
        // nodeid,
        // id
      }
      const action = formatUrl(`${settings.prefix}/resource/upload/:nodeid`, params)
      // const handleUpload = ({ file }) => {
      //   const {
      //     status,
      //     url
      //   } = file
      //   if (status === 'done') {
      //     setFieldsValue({
      //       value: url
      //     })
      //   }
      // }
      WrapComponent = 
        getFieldDecorator('value', {
            // valuePropName: 'file',
            rules: [
              {
                required: true,
                message: '必填字段',
              },
            ],
            initialValue: data.value,
            validateTrigger: false,
            getValueFromEvent: ({ file }) => {
              const {
                status,
                response
              } = file
              if (status === 'done') {
                const {
                  uuid: id
                } = getData(response)

                setFieldsValue({
                  'value': id
                })
                validateFields(['value'])
                return id
              }

              setFileList([file])
              return ''
            }
          })(
            <Upload.Dragger 
              name="file" 
              data={{
                ...params
              }}
              fileList={fileList}
              action={action}
              // onChange={handleUpload}
              onRemove={ file => {
                setFileList([])
              }}
              >
              <p className="ant-upload-drag-icon">
                <Icon name="inbox" size="3x" />
              </p>
              <p className="ant-upload-text">单击或拖动文件到此区域上传</p>
              <p className="ant-upload-hint">请上传单个文件</p>
            </Upload.Dragger>
          )
      break;
    // case 4 :
    case 3 :
      WrapComponent = 
        getFieldDecorator('value', {
          rules: [
            {
              required: true,
              message: '必填字段',
            },
          ],
          initialValue: data.value,
        })(
          <DatePicker
            style={{ width: '100%' }}
            showTime
            placeholder="请选择"
            format="YYYY-MM-DD HH:mm:ss"
          />
        )
      break;
    // case 2 :
    // case 6 :
    case 2 :
      WrapComponent = 
        getFieldDecorator('value', {
          rules: [
            {
              required: true,
              message: '必填字段',
            },
          ],
          initialValue: data.value,
        })(<InputNumber style={{ width: '100%' }} placeholder="请输入" />)
      break;
    // case 5 :
    case 4 :
      WrapComponent = 
        getFieldDecorator('value', {
          valuePropName: 'checked',
          initialValue: data.value,
        })(<Switch />)
      break;
    // case 0 :
    default :
      WrapComponent = 
        getFieldDecorator('value', {
          rules: [
            {
              required: true,
              message: '必填字段',
            },
          ],
          initialValue: data.value,
        })(<Input placeholder="请输入" />)
  }

  return (
    <Form layout="vertical">
      <Form.Item label="属性名称">
        {getFieldDecorator('name', {
          rules: [
            {
              required: true,
              message: '请输入属性名称',
            },
          ],
          initialValue: data.name,
        })(<Input placeholder="请输入" />)}
      </Form.Item>
      <Form.Item label="属性类型">
        {getFieldDecorator('ctype', {
          rules: [
            {
              required: true,
              message: '请输入属性类型',
            },
          ],
          initialValue: data.ctype == null ? types[0].id : data.ctype,
        })(
          <Select onChange={onTypeChange}>
            {options}
          </Select>
        )}
      </Form.Item>
      <Form.Item label="属性值">
        {WrapComponent}
      </Form.Item>
    </Form>
  );
})

const { TreeNode } = Tree;

const DictionaryPage = props => {
  const dispatch = useDispatch()
  const [loadedKeys, setLoadedKeys] = useState([])
  const [expandedKeys, setExpandedKeys] = useState([])
  const [selectedKeys, setSelectedKeys] = useState([])
  const [selectedRows, setSelectedRows] = useState([])
  // const { list = {}, params = {}, nodes = [] } = useSelector(_ => _.dictionary)
  const { list: data = [], nodes = [] } = useSelector(_ => _.dictionary)
  // const { data, total } = list
  const { effects } = useSelector(_ => _.loading)
  const loading = effects['dictionary/fetchList']

  useEffect(() => {
    dispatch(createAction('dictionary/fetchNodes')());
  }, [dispatch]);

  const columns = [
    {
      title: '属性名',
      dataIndex: 'name',
      width: 200,
    },
    {
      title: '属性类型',
      dataIndex: 'ctype',
      width: 200,
      align: 'center',
      render: (v, record, index) => {
        const type = types.filter(_ => _.id === v)[0]
        return type ? type.name : v
      }
    },
    {
      title: '属性值',
      dataIndex: 'value',
      width: 200,
      align: 'center',
    }
  ];
  const handleTreeReload = () => {
    dispatch(createAction('dictionary/resetNodes')());
    setLoadedKeys([])
    dispatch(createAction('dictionary/fetchNodes')());
  };
  const handleMenuEvent = (e, key) => {
    e.stopPropagation()

    const id = selectedKeys.length ? selectedKeys[0] : null

    dispatch(createAction('dictionary/resetNode')());

    switch (key) {
      case 'add':
        Dialog.open({
          effect: true,
          title: '添加节点',
          url: api.dictionary_node_add,
          data: {
            id
          },
          component: ModelForm,
          onOk: data => {
            handleTreeReload();
          }
        });
        break;
      case 'edit':
        Dialog.open({
          effect: true,
          title: '修改节点',
          url: api.dictionary_node_update,
          data: {
            id,
          },
          // options: {
          //   type: 'put',
          // },
          onOk: data => {
            handleTreeReload();
          },
          component: props => <ModelForm {...props} id={id} />,
          connect: ({ loading }) => ({ loading: loading.effects['dictionary/fetchNode'] }),
        });
        break;
      case 'remove':
        Dialog.confirm({
          title: '确认提示',
          content: '确定要删除已选择的节点？',
          onOk: async () => {
            await dispatch(createAction('dictionary/deleteNode')({
              id
            }))
            setSelectedKeys([])
            setExpandedKeys(expandedKeys.filter(_ => _.id !== id))
            handleTreeReload();
          },
        });
        break;
      default:
    }
  };
  const handleAdd = e => {
    dispatch(createAction('dictionary/reset')());
    const nodeid = selectedKeys.length ? selectedKeys[0] : null
    Dialog.open({
      effect: true,
      title: '新增扩展属性',
      data: {
        nodeid
      },
      component: ModelAttrForm,
      url: api.dictionary_attr_add,
      onOk: data => {
        handleReload();
      },
    });
  };
  const handleEdit = e => {
    const { id } = selectedRows[0];
    const nodeid = selectedKeys.length ? selectedKeys[0] : null
    dispatch(createAction('dictionary/reset')());
    Dialog.open({
      effect: true,
      title: '修改扩展属性',
      url: api.dictionary_attr_update,
      data: {
        nodeid,
        id,
      },
      // options: {
      //   type: 'put',
      // },
      onOk: data => {
        handleReload();
      },
      component: props => <ModelAttrForm {...props} id={id} />,
      connect: ({ loading }) => ({ loading: loading.effects['dictionary/fetchOne'] }),
    });
  };
  const handleRemove = e => {
    const { id } = selectedRows[0];
    const nodeid = selectedKeys.length ? selectedKeys[0] : null
    Dialog.confirm({
      title: '确认提示',
      content: '确定要删除已选择的扩展属性？',
      onOk: async () => {
        await dispatch(createAction('dictionary/delete')({
          nodeid,
          // id: selectedRows.map(_ => _.id)
          name: id
        }))
        handleReload();
      },
    });
  };
  const handleSelectRows = rows => {
    setSelectedRows(rows)
  };
  // const handleGridChange = (oldPagination, sorter) => {
  //   const pagination = getPagination(oldPagination);
  //   const payload = {
  //     ...params,
  //     ...pagination,
  //   };

  //   if (sorter.field) {
  //     payload.sorter = sorter.field;
  //     payload.order = sorter.order;
  //   }

  //   const id = selectedKeys[0]

  //   dispatch(createAction('dictionary/fetchList')({
  //     ...payload,
  //     nodeid: id
  //   }));
  // };
  const handleReload = () => {
    const id = selectedKeys[0]
    dispatch(createAction('dictionary/fetchList')({
      // ...params,
      nodeid: id
    }));
  };
  const handleSearch = async (value, e) => {
    e.preventDefault();
    // const pagination = getPagination({
    //   pageNumber: 1,
    // });

    // const id = selectedKeys[0]
    // dispatch(createAction('dictionary/fetchList')({
    //   ...params,
    //   ...pagination,
    //   name: value,
    //   nodeid: id
    // }));

    const id = selectedKeys[0]
    dispatch(createAction('dictionary/fetchList')({
      // ...params,
      // ...pagination,
      name: value,
      nodeid: id
    }));
  };
  const onSelect = (selectedKeys, info) => {
    setSelectedKeys(selectedKeys)
    if (selectedKeys.length) {
      dispatch(createAction('dictionary/fetchList')({
        nodeid: selectedKeys[0]
      }));
    }
  };
  const onExpand = expandedKeys => {
    setExpandedKeys(expandedKeys)
  }
  const onLoad = loadedKeys => {
    setLoadedKeys(loadedKeys)
  }
  const onLoadData = async treeNode => {
    if (!treeNode.props.children) {
      const { data } = await getNodes({
          id: treeNode.props.id
      })
      treeNode.props.dataRef.children = data

      dispatch(createAction('dictionary/updateState')({
        nodes: [...nodes]
      }))
    }
  }
  const renderTreeNodes = (data = []) =>
    data.map(item => {
      if (item.children) {
        return (
          <TreeNode title={item.value} key={item.id} dataRef={item} icon={<Icon name="folder-open" />}>
            {renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode {...item} title={item.value} key={item.id} dataRef={item} icon={<Icon name="folder-open" />} />;
    });

  const [dataSource, setDataSource] = useState([])
  
  const handleOptionSelect = (value, option) => {
    const ids = value.split('/')
    const id = ids[ids.length - 1]

    setExpandedKeys(ids)
    setSelectedKeys([id])
  }
  const renderOption = item => {
    const { name, names } = getQueryKeywords(item.s, item.name)
    
    return (
      <AutoComplete.Option key={item.path} text={name}>
        <span dangerouslySetInnerHTML={{__html: names}}></span>
      </AutoComplete.Option>
    )
  }
  const searchResult = (s, data) => (data || []).map(item => ({
    ...item,
    s
  }))
  const handleTreeSearch = async value => {
    if (value) {
      const data = await search({
        s: value
      })
      setDataSource(searchResult(value, data))
    } else {
      setDataSource([])
    }
  }

  // const pageNumber = params[settings.pageNumber];
  return (
    <Layout
      header={{
        icon: 'book',
        title: '数据字典',
      }}
      tools={
        <React.Fragment>
          <Button type="button" className="ico-btn" onClick={e => handleMenuEvent(e, 'add')}><Icon name="plus-square" /></Button>
          <Button type="button" className="ico-btn" onClick={e => handleMenuEvent(e, 'edit')} disabled={selectedKeys.length !== 1}><Icon name="edit" /></Button>
          <Button type="button" className="ico-btn" onClick={e => handleMenuEvent(e, 'remove')} disabled={selectedKeys.length !== 1}><Icon name="minus-square" /></Button>
        </React.Fragment>
      }
      query={
        <AutoComplete
          dataSource={dataSource.map(renderOption)}
          onSelect={handleOptionSelect}
          onSearch={handleTreeSearch}
          placeholder="请输入节点名称"
          optionLabelProp="text"
        >
          <Input suffix={<Icon name="search" />} />
        </AutoComplete>
      }
      side={
        <Tree 
          defaultExpandAll 
          showIcon 
          loadData={onLoadData}
          rowKey={record => record.id} 
          loadedKeys={loadedKeys}
          onLoad={onLoad}
          expandedKeys={expandedKeys}
          onExpand={onExpand}
          selectedKeys={selectedKeys}
          onSelect={onSelect} 
          >
          {renderTreeNodes(nodes)}
        </Tree>
      }
    >
      {
        selectedKeys.length > 0 ?
          <Layout
            toolbar={{
              left: (
                <React.Fragment>
                  <Button type="primary" onClick={handleAdd}>
                    新建
                </Button>
                  <Button onClick={handleEdit} disabled={selectedRows.length !== 1}>
                    编辑
                </Button>
                  <Button
                    type="danger"
                    disabled={selectedRows.length !== 1}
                    onClick={handleRemove}
                  >
                    删除
                </Button>
                </React.Fragment>
              ),
              right: (
                <Form layout="inline">
                  <Input.Search placeholder="请输入属性名称" onSearch={handleSearch} />
                </Form>
              ),
            }}
          >
            <Grid
              selectedRows={selectedRows}
              onSelectRow={handleSelectRows}
              columns={columns}
              data={data}
              loading={loading}
              // pagination={{
              //   pageNumber,
              //   total,
              // }}
              pagination={false}
              onReload={handleReload}
              // onChange={handleGridChange}
            />
          </Layout>
          :
          <Layout>
            <Layout.Hello></Layout.Hello>
          </Layout>
      }
    </Layout>
  );
}

export default DictionaryPage;
